package cn.monkey.family.server.domain.uc.auth.jwt;

import cn.monkey.family.data.KVPair;
import cn.monkey.family.data.uc.auth.Authorization;
import cn.monkey.family.data.jwt.JwtCreateOptions;
import cn.monkey.family.data.jwt.JwtProperties;
import cn.monkey.family.data.jwt.JwtUtils;
import cn.monkey.family.server.domain.uc.auth.AuthorizationManager;
import com.google.gson.Gson;
import io.jsonwebtoken.Claims;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.Map;
import java.util.function.Function;

public class JWTAuthorizationManager implements AuthorizationManager {

    private final JwtProperties jwtProperties;

    private final Function<Object, Authorization> authorizationDecoder;

    public JWTAuthorizationManager(JwtProperties jwtProperties,
                                   Function<Object, Authorization> authorizationDecoder) {
        this.jwtProperties = jwtProperties;
        this.authorizationDecoder = authorizationDecoder;
    }

    public JWTAuthorizationManager(JwtProperties jwtProperties) {
        Gson gson = new Gson();
        this.jwtProperties = jwtProperties;
        this.authorizationDecoder = authorization -> gson.fromJson(gson.toJson(authorization), Authorization.class);
    }

    @Override
    public String encrypt(Authorization authorization) {
        JwtCreateOptions.Builder builder = JwtCreateOptions.builder()
                .subject(this.jwtProperties.getSubject())
                .secret(this.jwtProperties.getSecret())
                .content(this.jwtProperties.getContent())
                .id(this.jwtProperties.getId());
        Map<String, Object> claims = this.jwtProperties.getClaims();
        if (!CollectionUtils.isEmpty(claims)) {
            builder.claims(claims);
        }
        builder.addClaim(KVPair.of(Authorization.KEY, authorization));
        long expireTimeMs = this.jwtProperties.getExpireTimeMs();
        if (expireTimeMs > 0L) {
            Date date = new Date();
            builder.issuedAt(date);
            builder.expiration(new Date(date.getTime() + expireTimeMs));
        }
        return JwtUtils.encrypt(builder.build());
    }

    @Override
    public Authorization decrypt(String s) {
        Claims claims = JwtUtils.decrypt(s, this.jwtProperties.getSecret());
        Object o = claims.get(Authorization.KEY);
        return o == null ? null : this.authorizationDecoder.apply(o);
    }

    @Override
    public boolean isValidKey(String key) {
        Claims claims = JwtUtils.decrypt(key, this.jwtProperties.getSecret());
        try {
            long exp = JwtUtils.getExp(claims);
            return (new Date()).getTime() < exp;
        } catch (NullPointerException var5) {
            return true;
        }
    }
}
